// Pipeline Component Library Example
// ----------------------------------
// Colin Bowern (colinbowern@hotmail.com)
// January 2007
//
// Copyright (c) 2007 Colin Bowern
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// * The above copyright notice and this permission notice shall be included in
//   all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#region References
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Text;
#endregion

namespace RockstarGuys.PipelineComponents
{
    /// <summary>
    /// The exception that is thrown when one of the arguments provided to a method is not of a valid type. 
    /// </summary>
    [Serializable, ComVisible(true)]
    public class ArgumentTypeException : ArgumentException
    {
        #region Fields
        private Type expectedType;
        #endregion

        #region Properties
        /// <summary>
        /// Gets the expected type.
        /// </summary>
        /// <value>The expected type.</value>
        public Type ExpectedType
        {
            get { return this.expectedType; }
        }

        /// <summary>
        /// Gets the error message and the parameter name, or only the error message if no parameter name is set.
        /// </summary>
        /// <value></value>
        /// <returns>A text string describing the details of the exception. The value of this property takes one of two forms: Condition Value The paramName is a null reference (Nothing in Visual Basic) or of zero length. The message string passed to the constructor. The paramName is not null reference (Nothing in Visual Basic) and it has a length greater than zero. The message string appended with the name of the invalid parameter. </returns>
        public override string Message
        {
            get
            {
                StringBuilder messageText = new StringBuilder(base.Message);

                if (this.ExpectedType != null)
                {
                    messageText.Append(Environment.NewLine);
                    messageText.AppendFormat(CultureInfo.CurrentCulture, StringResources.ParameterExpectedType, this.ExpectedType.FullName);
                }

                return messageText.ToString();
            }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        public ArgumentTypeException() : base(StringResources.ExceptionExpectedType_Generic) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <param name="context">The context.</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        protected ArgumentTypeException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            Helper.CheckForNullReference(info, "info");

            this.expectedType = (Type)info.GetValue("ExpectedType", typeof(Type));
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="innerException">The inner exception.</param>
        public ArgumentTypeException(string message, Exception innerException) : base(message, innerException) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        /// <param name="paramName">Name of the param.</param>
        public ArgumentTypeException(string paramName) : base(StringResources.ExceptionExpectedType_Generic, paramName) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        /// <param name="paramName">Name of the param.</param>
        /// <param name="message">The message.</param>
        public ArgumentTypeException(string paramName, string message) : base(message, paramName) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        /// <param name="paramName">Name of the param.</param>
        /// <param name="expectedType">The expected type.</param>
        public ArgumentTypeException(string paramName, Type expectedType)
            : base(StringResources.ExceptionExpectedType_Generic, paramName)
        {
            this.expectedType = expectedType;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:ArgumentTypeException"/> class.
        /// </summary>
        /// <param name="paramName">Name of the param.</param>
        /// <param name="expectedType">The expected type.</param>
        /// <param name="message">The message.</param>
        public ArgumentTypeException(string paramName, Type expectedType, string message)
            : base(message, paramName)
        {
            this.expectedType = expectedType;
        }
        #endregion

        #region Methods
        /// <summary>
        /// Gets the object data.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <param name="context">The context.</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            base.GetObjectData(info, context);
            info.AddValue("ExpectedType", this.ExpectedType, typeof(Type));
        }
        #endregion
    }
}
